package net.sf.nlp.ltag.extract;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import net.sf.nlp.ltag.data.LTAGNode;
import net.sf.nlp.ltag.util.LTAG;

public class LTAGRelation 
{
	private static final String HEADCHILD = "HEADCHILD_";
	private static final String ARGUMENT = "ARGUMENT_";
	private static final String MODIFIER = "MODIFIER_";
	private static final String COORDINATOR = "COORDINATOR";
	private static final String TAG ="TAG";
	private static final String SEPERATOR_REG = ", *";
	
	public static LTAGNode getHeadChildNode(LTAGNode node)
	{
		if (node.getChildren() == null || node.getChildren().size() == 0)
			return null;
		
		if (node.getChildren().size() == 1)
			return node.getChildren().get(0);
		
		List<CandidateHeadChild> headIndexList = new ArrayList<CandidateHeadChild>();
		List<CandidateHeadChild> modifierHeadIndexList = new ArrayList<CandidateHeadChild>();
		
		int index;
		
		String modifierTagStr = LTAG.relationProperties.getProperty(MODIFIER + TAG);
		String candidateStr = LTAG.relationProperties.getProperty(HEADCHILD + node.getNodeText());
		
		if (candidateStr == null)
			System.out.println("The head child candidates of " +  node.getNodeText() + " is empty!");
		
		List<String> modifierTags = Arrays.asList(modifierTagStr.split(SEPERATOR_REG));
		List<String> candidates = Arrays.asList(candidateStr.split(SEPERATOR_REG));
		
		for (LTAGNode child : node.getChildren())
		{
			if (child.isIntermediateNode() && child.getNodeText().equals(node.getNodeText()))
				return child;
			
			index = candidates.indexOf(child.getNodeText());
			
			if (index == -1)
				continue;
			
			if (child.getSemanticTag() != null && modifierTags.contains(child.getSemanticTag()))
				modifierHeadIndexList.add(0, new CandidateHeadChild(index, child));
			else
			{
				headIndexList.add(0, new CandidateHeadChild(index, child));
			}
		}
		
		if (headIndexList.size() > 0)
		{
			Collections.sort(headIndexList);
			return headIndexList.get(0).getCandidateHeadChild();
		}
		else if (modifierHeadIndexList.size() > 0)
		{
			Collections.sort(modifierHeadIndexList);
			return modifierHeadIndexList.get(0).getCandidateHeadChild();
		}
		
		return null;
	}
	
	public static boolean isArgumentNode(LTAGNode headChild, LTAGNode node)
	{
		//if (!headChild.getNodeText().startsWith("V") && !headChild.getNodeText().startsWith("PP"))
		//	return false;
		
		String modifierTagStr = LTAG.relationProperties.getProperty(MODIFIER + TAG);
		String argCandidateStr0 = LTAG.relationProperties.getProperty(ARGUMENT + headChild.getParent().getNodeText() + "_"+ headChild.getNodeText());
		String argCandidateStr = LTAG.relationProperties.getProperty(ARGUMENT + headChild.getNodeText());
		String argumentTagStr = LTAG.relationProperties.getProperty(ARGUMENT + TAG);
		
		List<String> modifierTags = Arrays.asList(modifierTagStr.split(SEPERATOR_REG));
		List<String> argumentTags = Arrays.asList(argumentTagStr.split(SEPERATOR_REG));
		
		List<String> argCandidates0 = null;
		if (argCandidateStr0 != null)
			argCandidates0 = Arrays.asList(argCandidateStr0.split(SEPERATOR_REG));
		
		List<String> argCandidates = null;
		if (argCandidateStr != null)
			argCandidates = Arrays.asList(argCandidateStr.split(SEPERATOR_REG));
		
		if (node.getSemanticTag() != null && modifierTags.contains(node.getSemanticTag()))
			return false;
		
		if (node.getSemanticTag() != null && argumentTags.contains(node.getSemanticTag()))
			return true;
		
		if (argCandidates0 != null)
		{
			if (argCandidates0.contains(node.getNodeText()))
				return true;
		}
		
		if (argCandidates != null)
		{
			if (argCandidates.contains(node.getNodeText()))
				return true;
		}
			
		return false;
	}
	
	public static boolean isModifierNode(LTAGNode headChild, LTAGNode node)
	{
		String  modifierTagStr = LTAG.relationProperties.getProperty(MODIFIER + TAG);
		String modifierCandidateStr = LTAG.relationProperties.getProperty(MODIFIER + headChild.getNodeText());
		
		List<String> modifierTags = Arrays.asList(modifierTagStr.split(SEPERATOR_REG));
		
		List<String> modifierCandidates = null;
		if (modifierCandidateStr != null)
			modifierCandidates = Arrays.asList(modifierCandidateStr.split(SEPERATOR_REG));
		
		if (node.getSemanticTag() != null && modifierTags.contains(node.getSemanticTag()))
			return true;
		
		if (modifierCandidates != null && modifierCandidates.contains(node.getNodeText()))
			return true;
		
		boolean isArgument = isArgumentNode(headChild, node);
		
		return !isArgument;
	}
	
	public static boolean isCoordinationNode(LTAGNode node)
	{
		List<LTAGNode> parentChild = node.getParent().getChildren();
		int index = parentChild.indexOf(node);
		
		if (index == 0 || index == parentChild.size() - 1)
			return false;
		
		String coordinatorStr = LTAG.relationProperties.getProperty(COORDINATOR);
		
		List<String> coordinator = Arrays.asList(coordinatorStr.split(SEPERATOR_REG));
		
		if (coordinator.contains(node.getNodeText()))
			return true;
		
		//if ("PU".equals(node.getNodeText()) && "、".equals(node.getWord().getLexical()))
		if ("PU".equals(node.getNodeText()))
			return true;
		
		return false;
	}
	
	public static void validateRelation(LTAGNode headChild, List<LTAGNode> argumentNodes, List<LTAGNode> modifierNodes)
	{
		validateArgumentRelation(headChild, argumentNodes, modifierNodes);
		validateModifierRelation(headChild, argumentNodes, modifierNodes);
	}
	
	private static void validateArgumentRelation(LTAGNode headChild, List<LTAGNode> argumentNodes, List<LTAGNode> modifierNodes)
	{
		if (argumentNodes.size() == 0)
			return;
		
		List<LTAGNode> children = headChild.getParent().getChildren();
		int headIndex = children.indexOf(headChild);
		
		for (int i = argumentNodes.size() - 1; i >= 0; i--)
		{
			LTAGNode argumentNode = argumentNodes.get(i);
			int argumentIndex = children.indexOf(argumentNode);
			
			if (Math.abs(headIndex - argumentIndex) > 1)
				moveArgument2Modifier(children, argumentNodes, modifierNodes, i);
		}
	}
	
	private static void validateModifierRelation(LTAGNode headChild, List<LTAGNode> argumentNodes, List<LTAGNode> modifierNodes)
	{
		if (modifierNodes.size() == 0)
			return;
	}
	
	private static void moveArgument2Modifier(List<LTAGNode> children, List<LTAGNode> argumentNodes, List<LTAGNode> modifierNodes, int argumentIndex)
	{
		LTAGNode node = argumentNodes.remove(argumentIndex);
		
		int i;
		for (i = 0; i < modifierNodes.size(); i++)
		{
			LTAGNode modifierNode = modifierNodes.get(i);
			int modifierIndex = children.indexOf(modifierNode);
			
			if (children.indexOf(node) < modifierIndex)
			{
				modifierNodes.add(i, node);
				break;
			}
		}
		
		if (i == modifierNodes.size())
			modifierNodes.add(i, node);
	}
}

class CandidateHeadChild implements Comparable<CandidateHeadChild>
{
	int index;
	LTAGNode candidateHeadChild;

	public CandidateHeadChild(int index, LTAGNode candidateHeadChild)
	{
		this.index = index;
		this.candidateHeadChild = candidateHeadChild;
	}
	
	public int getIndex() 
	{
		return index;
	}

	public LTAGNode getCandidateHeadChild() 
	{
		return candidateHeadChild;
	}

	@Override
	public int compareTo(CandidateHeadChild headChild) 
	{
//		if (candidateHeadChild.getMinLevel()  <= 2 && candidateHeadChild.getMinLevel() < headChild.getCandidateHeadChild().getMinLevel())
//			return -1;
//		else if (headChild.getCandidateHeadChild().getMinLevel() <= 2 && candidateHeadChild.getMinLevel() > headChild.getCandidateHeadChild().getMinLevel())
//			return 1;
//		else
			return Integer.valueOf(index).compareTo(headChild.getIndex());
	}
	
}
